package br.mikhas.task.application;

import java.util.Collection;
import java.util.Date;

import br.mikhas.task.History;
import br.mikhas.task.SimpleTaskBean;
import br.mikhas.task.Task;
import br.mikhas.task.TaskList;
import br.mikhas.task.data.HistoryRepository;
import br.mikhas.task.data.TaskRepository;
import br.mikhas.task.metadata.HolidayCalendar;

/**
 * 
 * @author Mikhail Domanoski
 * 
 */
public class TaskService {

	/**
	 * Tasks repository
	 */
	private TaskRepository taskRepository;

	private HistoryRepository historyRepository;

	/**
	 * Cause to begin the scheduling process
	 */
	public void schedule() {
		Collection<Task> tasks = taskRepository.getRecurrent();
		Date schedulingDate = new Date();

		for (Task task : tasks) {
			if (this.maySchedule(schedulingDate, task)) {
				Task occurrence = createOccurrence(task, schedulingDate);

				History history = History.occurrenceCreation(occurrence);

				historyRepository.save(history);
				this.taskRepository.save(occurrence);
			}
		}
	}

	/**
	 * Checks if a task may be scheduled
	 * 
	 * @param date
	 *            The date to schedule the task
	 * @param task
	 *            The task to check
	 * @return <tt>true</tt> if the task recurrence matches the date
	 */
	private boolean maySchedule(Date date, Task task) {
		Date start = task.getStart();
		String recurrence = task.getRecurrence();
		TaskList taskList = task.getList();
		Collection<HolidayCalendar> calendars = taskList.getHolidayCalendars();

		if (date.compareTo(start) >= 0) {
			if (RecurrenceMatcher.matchDate(date, recurrence, calendars)) {
				return !this.taskRepository.hasOcurrenceForDate(date, task);
			}
		}

		return false;
	}

	private Task createOccurrence(Task task, Date date) {
		Task occurrence = new SimpleTaskBean(task, date);
		return occurrence;
	}

	public void setHistoryRepository(HistoryRepository historyRepository) {
		this.historyRepository = historyRepository;
	}

	public void setTaskRepository(TaskRepository taskRepository) {
		this.taskRepository = taskRepository;
	}
}
